Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

SqlTemplate: шаблонизатор SQL запросов (Rin)
Author Message
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Thu Jun 28, 2007 4:17 pm (написано за 20 минут 34 секунды)
   Post subject: SqlTemplate: шаблонизатор SQL запросов
Reply with quote

Все привыкли к тому, что для разделения логики и внешнего вида используются html шаблонизаторы.
Как на счет использования sql шаблонизатора?

Это новая концепция шаблонизатора SQL запросов
Некоторые идеи были заимствованы у DbSimple (dklab.ru/lib/DbSimple/) и PDO (ru.php.net/pdo).
Основные правила и примеры даны выше.

Класс используется в библиотеке MysqlRapid (forum.dklab.ru/viewtopic.php?p=139350).
Code (php): скопировать код в буфер обмена
/**
 * Шаблонизатор SQL запросов
 *
 * Предназначение:
 *   * Избавление программиста от рутины составления динамических SQL запросов
 *   * Увеличние читабельности SQL запросов
 *   * Усиление безопасности, защита от SQL-инъекций
 *
 * Возможности:
 *   * замена меток-строк на их квотированные значения из ассоциативных многомерных массивов
 *   * автоматическое преобразование пустых строк в значения NULL
 *   * условное включение частей SQL кода в опциональных макроблоках {...}
 *   * итерация опциональных макроблоков
 *   * разделение SQL кода по разделителю ";" на несколько запросов
 *   * включение частей SQL кода из внешних файлов
 *   * поддерживаемые кодировки шаблона -- UTF-8 или любая однобайтовая
 *
 * Метки строки могут находиться внутри строковых выражений!
 * Массив меток-заменителей может содержать не проверенные на корректность данные.
 * К примеру, в шаблоне удобно использовать массив $_REQUEST ($_GET, $_POST, $_COOKIE, $_SESSION).
 * Метки-заменители с сомнительными значениями НЕОБХОДИМО помещать в макроблоки {...}.
 * В случае, если значение не существует или не корректно, макроблок будет удален.
 * Все пустые строковые значения (ноль байт) автоматически преобразуются в NULL.
 *
 * Формат метки-заменителя в SQL шаблоне:
 *   ?<тип><модификаторы>[:<имя>]
 *
 * Типы:
 *   ?#  Значение квотируется как идентификатор, например: `field`
 *   ?r  Значение НЕ квотируется и вставляется как есть,
 *       используется только для вставки кусков SQL кода!
 *       Вы д.б. уверены, что это безопасно и не разрушит SQL код!
 *   ?s  Значение квотируется стандартным образом для строки, например: 'value\'1'
 *   ?b  Значение преобразуется в логический формат и квотируется в '1' или '0'
 *   ?h  Значение квотируется через bin2hex(), т.е. данные преобразуются в шестнадцатиричное представление, например: 0xD182D0B5D181D182
 *   ?i  Значение квотируется как целое число: integer
 *   ?d  Синоним для ?i
 *   ?f  Значение квотируется как число с плавающей запятой: float (знак ',' автоматически заменяется на '.')
 * Модификаторы:
 *   a  Значения массива квотируются и перечисляются через запятую
 *   k  Значения берутся из ключей ассоциативного массива, квотируются и перечисляются через запятую
 *   A  Ключи и значения ассоциативного массива, форматируется как <идентификатор> = <значение>
 *      и перечисляются через зяпятую. Пример запроса: "UPDATE t1 SET ?A:values"
 *   v  Значения массива явл. двумерным массивом и используются для квотирования значений
 *      при многострочной вставке записей, например: "INSERT INTO t1 (c1, c2) VALUES ?v:values"
 *   +  Значение не м.б. пустым или NULL
 *   @  Если метка заменитель не существует, скалярное значение воспринимается как NULL (модификатор д.б. последним)
 *      Используется, если макроблок использовать нельзя -- нужно обязательно вставить значение NULL (например, при обновлении записи)
 *      Для модификаторов [akA] этот модификатор не действует.
 * Имя:
 *   Задается в формате  <имя>[[<имя>]...], т.е. имя м.б. ассоциативным многомерным массивом
 *
 * Если тип не указан, то подразумевается "s".
 * Если модификатор не указан, то подразумевается значение скалярного типа или NULL.
 *
 * Примеры
 *   исходный массив:
 *   $placeholders = array(
 *      '_REQUEST' => array('group_ids' => array(14, 57, '83', '')),
 *      'person'   => array('age' => '29', 'weight' => '80', 'dob' => '', 'name' => 'Ivanov'),
 *      'dob'      => '1977-09-10',
 *      'words'    => array('a', 'b'),
 *   )
 *
 *   результат преобразования:
 *   "?ia:_REQUEST[group_ids]"        => "14, 57, 83, 0"
 *   "?iA:person"                     => "`age` = 29, `weight` = 80, `dob` = NULL, `name` = 'Ivanov'"
 *   "?#k:person"                     => "`age`, `weight`, `dob`, `name`"
 *   "person.dob N!= ?s:person[dob]"  => "person.dob IS NOT NULL"
 *   "LIKE '%?s:person[name]%'"       => "LIKE '%Ivanov%'"
 *   "person.dob > ?s:dob"            => "person.dob > '1977-09-10'"
 *   в предположении, что ключ HTTP_X_FORWARDED_FOR не существует:
 *   "?@:_SERVER[HTTP_X_FORWARDED_FOR]" => "NULL"
 *   "{HTTP_X_FORWARDED_FOR = ?:_SERVER[HTTP_X_FORWARDED_FOR]}" => " "
 *   итерируемые макроблоки:
 *   "{MAX(word = ?s:words[]) +} 0" => "MAX(word = 'a') + MAX(word = 'b') + 0"
 *
 * Автозамены
 *   Используются для автозамены условий "N=" и "N!=" на "IS NULL" и "IS NOT NULL" соответственно.
 *   Удобно использовать в контексте sql-условий для сравнения значений.
 *
 * Макроблоки
 *   Макроблоки используются для условного сохранения или удаления блоков вида {...} в SQL запросе.
 *   Макроблоки могут быть вложены друг в друга: {... {...} }
 *   Содержимое макроблока сохраняется, если существуют все метки-заменители, указанные в блоке.
 *   Существование метки-заменителя проверяется по ключу в ассоц. массиве $placeholders,
 *   а если указан модификатор +, то и по значению, которое не д.б. пустым или NULL.
 *   Если хотябы одно значение не существует или ошибочно (неверный тип), макроблок удаляется.
 *   При этом все вложенные в него макроблоки тоже будут удалены.
 *
 * Итерируемые макроблоки
 *   Макроблок становится еще и итерируемым, если в макроблоке встречается хотя бы одна метка-заменитель,
 *   которая оканчивается на "[]". Значением метки-заменителя д.б. массив.
 *   При каждой итерации макроблок копируется с новыми значениями этого массива.
 *
 * Включение кода шаблона из внешних файлов (*.sqlt)
 *   Эта возможность поддерживается, если основной шаблон SQL кода так же загружен из файла.
 *   Текущая директория -- это директория, откуда подгружается основной шаблон.
 *   Синтаксис: ?<file://<имя_файла>>
 *   Пример:    ?<file://_general.fields.sqlt>
 *
 * @license  http://creativecommons.org/licenses/by-nc-sa/3.0/
 * @author   Nasibullin Rinat <n a s i b u l l i n  at starlink ru>
 * @charset  ANSI
 * @version  1.8.0
 */



t_SqlTemplate-1.8.0.rar
 Description:
Тесты

Download
 Filename:  t_SqlTemplate-1.8.0.rar
 Filesize:  1.84 KB
 Downloaded:  1106 Time(s)


SqlTemplate-1.8.0.rar
 Description:
Шаблонизатор SQL кода

Download
 Filename:  SqlTemplate-1.8.0.rar
 Filesize:  8.92 KB
 Downloaded:  1005 Time(s)



Last edited by Rin on Fri May 16, 2008 9:13 pm; edited 27 times in total
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Thu Jul 12, 2007 10:58 am (спустя 13 дней 18 часов 40 минут; написано за 5 минут 24 секунды)
   Post subject:
Reply with quote

НОВОЕ:
  1. Добавлено разделение SQL кода по разделителю ";" на несколько запросов, т.о. функция возвращает массив SQL запросов, если их несколько
      
  2. Обработка синтаксиса для разных баз данных (MySQL, PostgreSQL, InterBase, Oracle);
Знатоков прошу проверить корретность диалектов БД, описанных в статическом массиве $_schemas.

Last edited by Rin on Wed Jul 25, 2007 12:25 pm; edited 1 time in total
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Wed Jul 25, 2007 12:20 pm (спустя 13 дней 1 час 22 минуты; написано за 4 минуты 42 секунды)
   Post subject:
Reply with quote

НОВОЕ:
  1. включение SQL кода из внешних файлов *.sqlt
  2. оптимизация скорости
  3. другие мелкие правки и улучшения
Модераторы, пожалуйста, перенесите тему в "Склад готовых решений PHP". Спасибо :)

Last edited by Rin on Mon Sep 01, 2008 1:07 pm; edited 4 times in total
Back to top
View user's profile Send private message Send e-mail
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Sun Jul 29, 2007 11:27 am (спустя 3 дня 23 часа 6 минут; написано за 10 секунд)
   Post subject:
Reply with quote


М

посмотрел тему на phpclub - вроде и там и здесь аргументы и ответы совпадают, так что

Ветка выделена в отдельную тему «мусор»,
расположенную в форуме Мусоропровод (29 Июля 2007, 11:27).


Last edited by Maus on Sun Jul 29, 2007 11:28 am; edited 1 time in total
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Sun Jul 29, 2007 11:28 am (спустя 1 минуту 4 секунды; написано за 29 секунд)
   Post subject:
Reply with quote

попытка обсуждения на phpclub: phpclub.ru/talk/showthread.php?threadid=101340
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Mon Jul 30, 2007 11:01 am (спустя 23 часа 33 минуты)
   Post subject:
Reply with quote


М

Ветка выделена в отдельную тему «мусор»,
расположенную в форуме Мусоропровод (30 Июля 2007, 11:01).
Back to top
View user's profile Send private message
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Mon Jul 30, 2007 11:51 am (спустя 49 минут; написано за 8 минут 19 секунд)
   Post subject:
Reply with quote

НОВОЕ:
1.1.4
  1. Добавлен модификатор + (см. документацию)
1.1.5
  1. Дополнена документация
      
  2. $info['DMS'] возвращает SQL оператор выборки или манипуляции данных в верхнем регистре
      
  3. Исправлена ошибка трактовки однострочного комментария в запросе, подобного UPDATE account SET credit=credit--123
      
  4. Добавлена обработка комментария # для MySQL
      
  5. Другие мелкие правки и улучшения
1.1.6
  1. Исправлена ошибка квотирования значения для меток-заменителей логического типа (?b), если они используются в строковых выражениях SQL кода
1.1.7
  1. Исправлена ошибка для пустого однострочного комментария в запросе (--)
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Thu Oct 04, 2007 9:56 am (спустя 2 месяца 4 дня 22 часа 5 минут; написано за 1 минуту 17 секунд)
   Post subject:
Reply with quote

1.2.0
  1. Добавлена проверка значений на непустой массив для меток-заменителей с модификаторами [akA].
    Если массив пустой, то считается, что метка-заменитель не существует.
  2. Добавлен модификатор @ (д.б. последним), который создает следующее правило.
    Если метка-заменитель не существует, скалярное значение воспринимается как NULL
    Используется, если макроблок использовать нельзя -- нужно обязательно вставить значение (например, при обновлении записи)
    Для модификаторов [akA] этот модификатор не действует.
  3. Изменен синтаксис автозамены знака "=" на "IS" и "!=" на "IS NOT" для NULL значений.
    Теперь для этих целей используются "N=" и "N!=" соответственно.
    Это позволяет управлять автозаменой в зависимости от контекста присваивания (INSERT ...) или сравнения (SELECT ...).
  4. Если ключей '_REQUEST / _SERVER / _SESSION' в массиве меток-заменителей $placeholders не существует,
    то они создается со значениями из суперглобальных переменных $_REQUEST / $_SERVER / $_SESSION
  5. Исправлена ошибка, при которой в массиве $info['errors'][<placeholder>]
    не показывалось полное имя метки-заменителя в альтернативном синтаксисе.
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Thu Oct 11, 2007 10:06 am (спустя 7 дней 10 минут; написано за 51 секунду)
   Post subject:
Reply with quote

1.2.1
  1. Добавлен модификатор "v"
    Значения массива явл. двумерным массивом и используются для квотирования значений
    при множественной вставке записей, например: "INSERT INTO t1 (c1,c2) VALUES ?v:values"
  2. Исправлена небольшая ошибка грамматического разбора вхождения "<table>.<caption>",
    где имя таблицы и колонки м.б. метками-заменителями.
  3. Другие незначительные внутренние правки.
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Thu Nov 22, 2007 11:40 am (спустя 1 месяц 11 дней 1 час 33 минуты; написано за 31 секунду)
   Post subject:
Reply with quote

1.3.0
  1. В названиях меток-строк в квадратных скобках теперь м.б. указаны любые печатаемые символы.
  2. Отменено следующее правило: внешний макроблок сохраняется, если сохранились все внутренние (вложенные в него) макроблоки. Если нужна такая функциональность, достаточно иметь один макроблок.
  3. Если ключа _FILES в массиве меток-заменителей $placeholders не существует, то он создается автоматически со значением из суперглобальной переменной $_FILES
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Wed Nov 28, 2007 11:40 am (спустя 6 дней 21 секунду; написано за 16 секунд)
   Post subject:
Reply with quote

1.4.0
  1. Убрана поддержка короткого синтаксиса меток-заменителей для увеличения производительности в 1,5 - 2 раза.
Back to top
View user's profile Send private message Send e-mail
Guest






Карма: 388
   поощрить/наказать


PostPosted: Sat Dec 08, 2007 7:42 pm (спустя 10 дней 8 часов 1 минуту; написано за 9 секунд)
   Post subject:
Reply with quote

Code (php): скопировать код в буфер обмена
$digests = array (www.php.net/array)();
$i = 0;
foreach($res3 as $a){
        $sql = 'SELECT * FROM fbg_cr_digestField WHERE digestId = "'.$a['id'].'"';
        $res5 = $db->fassoc($sql);
        $digests[$i] = $a;
        foreach($res5 as $b){
                $digests[$i]['fields'][$b['id']] = $b;
        }
        $i++;
}
Back to top
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Thu Feb 21, 2008 4:04 pm (спустя 2 месяца 12 дней 20 часов 22 минуты; написано за 50 секунд)
   Post subject:
Reply with quote

1.5.0
  1. Добавлена поддержка меток-заменителей внутри псевдонимов, например: d.`caption__?#:_REQUEST[lang]`
  2. Добавлена поддержка итерируемых макроблоков с метками-заменителями с окончанием на '[]'.
1.6.0
  1. Модификатор "N" больше не используется.
    Добавлено автоматическое преобразование пустых значений в NULL.
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Fri Mar 28, 2008 1:17 pm (спустя 1 месяц 6 дней 21 час 13 минут; написано за 1 минуту 45 секунд)
   Post subject:
Reply with quote

1.6.1
  1. Исправлены ошибки для итерируемых макроблоков
1.7.0
  1. SqlTemplate() теперь сделан в виде класса.
  2. Синтаксис ?<тип><модификаторы>:[<имя>] эквивалентен ?<тип><модификаторы>:<имя>.
    Сделано для поддержки конструкций типа `?#:[table]_tree`.
1.7.1
  1. Исправлена ошибка в проверке существования метки-заменителя
1.7.2
  1. Исправлена ошибка в обработке итерируемых макроблоков
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Fri May 16, 2008 9:14 pm (спустя 1 месяц 19 дней 7 часов 56 минут; написано за 46 секунд)
   Post subject:
Reply with quote

1.8.0
  1. Значения числовых меток-заменителей при квотировании дополнительно проверяются на рег. выражение '/^-?\d+$/s' или функцией is_numeric() в зависимости от модификатора i, d, f.
    Если значение не проходит проверку, возвращается 0.
    Изменение сделано в связи с тем, что в PHP строка intval("123abc") возвращает число 123, а запрос (SELECT "123abc" = 123) возвращает 1. Но такое поведение м.б. не желательным в ряде случаев и нарушать логику работы программы, поэтому сделана более строгая проверка.
  2. Отменена автоматическая замена ',' на '.' в числах, см. функцию setlocale()
  3. Исправлена ошибка в обработке макроблоков: фигурные скобки так же могут использоваться внутри строк и идентификаторов полей.
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Mon Sep 01, 2008 1:11 pm (спустя 3 месяца 15 дней 15 часов 57 минут; написано за 2 минуты 18 секунд)
   Post subject:
Reply with quote

Если для вас важна скорость, не используйте этот класс.
В MysqlRapid (forum.dklab.ru/viewtopic.php?t=26693) этот класс больше не используется.

Вопрос решен, тему можно закрыть.
Back to top
View user's profile Send private message Send e-mail
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Sat Sep 06, 2008 12:56 am (спустя 4 дня 11 часов 44 минуты)
   Post subject:
Reply with quote


М

Тема закрыта.
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   This topic is locked: you cannot edit posts or make replies. All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML